/**
 * $Id: ParsingStats.java 23 2006-09-17 20:02:05Z willi.w $
 */
package at.wwu.tunes2db.export;

import java.io.IOException;
import java.sql.SQLException;
import java.util.*;


import org.apache.commons.math.stat.Frequency;
import org.apache.commons.math.stat.descriptive.SummaryStatistics;
import org.apache.log4j.Logger;

import at.wwu.tunes2db.types.*;
import at.wwu.tunes2db.utils.PercentageComparator;

public class ParsingStats implements Destination {

    private static final Logger log = Logger.getLogger(ParsingStats.class.getName());

    Hashtable<String, SummaryStatistics> summaryStats = new Hashtable<String, SummaryStatistics>();

    Hashtable<String, Frequency> freqStats = new Hashtable<String, Frequency>();

    HashSet<Genre> genres = new HashSet<Genre>();

    HashSet<Artist> artists = new HashSet<Artist>();

    public boolean addAlbum(Album l) throws SQLException {
        if (l != null) {
            if (l.isNew()) {
                if (l.getName() != null) {
                    summaryStats.get("albumName").addValue(l.getName().length());
                }
            }
        }
        return false;
    }

    public boolean addArtist(Artist a) throws SQLException {
        if (a != null) {
            if (a.isNew()) {
                if (a.getName() != null) {
                    artists.add(a);
                    summaryStats.get("artistName").addValue(a.getName().length());
                }
                freqStats.get("artist").addValue(a.getName());
            }
        }
        return false;
    }

    public boolean addGenre(Genre g) throws SQLException {
        if (g != null) {
            if (g.isNew()) {
                if (g.getName() != null) {
                    genres.add(g);
                    summaryStats.get("genreName").addValue(g.getName().length());
                }
            }
            freqStats.get("genre").addValue(g.getName());
        }
        return false;
    }

    public boolean addTrack(Track t) throws SQLException {
        if (t != null) {
            if (t.getTotal_time() > 0 && t.getTotal_time() < 100 * 60 * 60 * 2) {
                summaryStats.get("trackLength").addValue(t.getTotal_time());
                // 1ms <-> 2h 
            }
            if (t.getSize() > 0) {
                summaryStats.get("trackSize").addValue(t.getSize());
                // 1ms <-> 2h 
            }
            summaryStats.get("trackName").addValue(t.getName().length());
        }
        return false;
    }

    public void open() throws ClassNotFoundException, SQLException, IOException {
        summaryStats.put("trackLength", SummaryStatistics.newInstance());
        summaryStats.put("trackSize", SummaryStatistics.newInstance());
        summaryStats.put("trackName", SummaryStatistics.newInstance());
        summaryStats.put("artistName", SummaryStatistics.newInstance());
        summaryStats.put("albumName", SummaryStatistics.newInstance());
        summaryStats.put("genreName", SummaryStatistics.newInstance());
        freqStats.put("genre", new Frequency());
        freqStats.put("artist", new Frequency());
    }

    public void close() {
        log.info("Parsing Statistics:");
        /*log.info("TrackLength: " + Formatter.formatMilliseconds(summaryStats.get("trackLength").getMin()) + " min, "
         + Formatter.formatMilliseconds(summaryStats.get("trackLength").getMax()) + " max, "
         + Formatter.formatMilliseconds(summaryStats.get("trackLength").getMean()) + " avg");
         log.info("TrackSize: " + Formatter.formatBytes(summaryStats.get("trackSize").getMin()) + " min, "
         + Formatter.formatBytes(summaryStats.get("trackSize").getMax()) + " max, "
         + Formatter.formatBytes(summaryStats.get("trackSize").getMean()) + " avg");
         log.info("TrackName: " + Formatter.formatNumber(summaryStats.get("trackName").getMin()) + " min, "
         + Formatter.formatNumber(summaryStats.get("trackName").getMax()) + " max");
         log.info("ArtistName: " + Formatter.formatNumber(summaryStats.get("artistName").getMin()) + " min, "
         + Formatter.formatNumber(summaryStats.get("artistName").getMax()) + " max");
         log.info("AlbumName: " + Formatter.formatNumber(summaryStats.get("albumName").getMin()) + " min, "
         + Formatter.formatNumber(summaryStats.get("albumName").getMax()) + " max");
         log.info("GenreName: " + Formatter.formatNumber(summaryStats.get("genreName").getMin()) + " min, "
         + Formatter.formatNumber(summaryStats.get("genreName").getMax()) + " max");*/
        log.info(topXGenres(10, freqStats.get("genre"), genres));
        log.info(topXArtists(10, freqStats.get("artist"), artists));
        freqStats.get("artist").toString();
    }

    public String topXGenres(int x, Frequency stats, HashSet<Genre> genre) {
        TreeMap<Double, String> sorted = new TreeMap<Double, String>(new PercentageComparator());
        String value = null;
        StringBuffer result = new StringBuffer("Genres\n");
        int i = 0;
        for (Genre g : genre) {
            value = Math.round(stats.getPct(g.getName()) * 1000) / 10 + "% " + g.getName() + "\n";
            sorted.put(new Double(stats.getPct(g.getName())), value);
        }
        for (String se : sorted.values()) {
            if (i++ < x) {
                result.append(se);
            }
        }
        return result.toString();
    }

    public String topXArtists(int x, Frequency stats, HashSet<Artist> artist) {
        TreeMap<Double, String> sorted = new TreeMap<Double, String>(new PercentageComparator());
        String value = null;
        StringBuffer result = new StringBuffer("Artists\n");
        int i = 0;
        for (Artist a : artist) {
            value = Math.round(stats.getPct(a.getName()) * 1000) / 10 + "% " + a.getName() + "\n";
            sorted.put(new Double(stats.getPct(a.getName())), value);
        }
        for (String se : sorted.values()) {
            if (i++ < x) {
                result.append(se);
            }
        }
        return result.toString();
    }

    public boolean addKind(Kind k) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    public boolean addType(Type k) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }
}
